home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / CLASSSRC.PAK / OBJSTRM.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  17KB  |  767 lines

  1. //----------------------------------------------------------------------------
  2. // Borland Class Library
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   5.9  $
  6. //
  7. //----------------------------------------------------------------------------
  8. #include <classlib/pch.h>
  9. #include <classlib/streambl.h>
  10. #include <classlib/objstrm.h>
  11. #include <services/checks.h>
  12. #include <services/cstring.h>
  13. #include <services/memory.h>
  14. #include <tchar.h>
  15.  
  16. DIAG_DEFINE_GROUP(Objstrm,1,0);
  17.  
  18. const uint32 streamVersion = 0x0101;
  19. const _TCHAR versionIndicator = ':';
  20.  
  21. const _TCHAR EOS = '\0';
  22.  
  23. const uint8  oldNullStringLen = UCHAR_MAX;
  24. const uint32 nullStringLen = ULONG_MAX;
  25.  
  26. TStreamableTypes *pstream::types = 0;
  27.  
  28. const _TCHAR *TStreamer::StreamableName() const
  29. {
  30.     return 0;
  31. }
  32.  
  33. TStreamableClass::TStreamableClass( const _TCHAR *n,
  34.                                     BUILDER b,
  35.                                     int d,
  36.                                     ModuleId id ) :
  37.     ObjectBuilder( b, d ),
  38.     ModId(id)
  39. {
  40.     ObjectId = new _TCHAR[_tcslen(n)+1];
  41.     _tcscpy( CONST_CAST(_TCHAR *,ObjectId), n );
  42.     pstream::initTypes();
  43.     if( id != 0 )   // id == 0 is used only during lookup.
  44.                     // It flags an instance that shouldn't be registered
  45.         pstream::types->RegisterType( id, *this );
  46. }
  47.  
  48. TStreamableClass::~TStreamableClass()
  49. {
  50.     if( ModId != 0 )
  51.         pstream::types->UnRegisterType( ModId, *this );
  52.  
  53.     delete [] CONST_CAST(_TCHAR *,ObjectId);
  54. }
  55.  
  56. void TStreamableTypes::RegisterType( ModuleId, TStreamableClass& ts )
  57. {
  58.     Types.Add(&ts);
  59. }
  60.  
  61. void TStreamableTypes::UnRegisterType( ModuleId, TStreamableClass& ts )
  62. {
  63.     Types.Detach(&ts);
  64.     if( Types.Count() == 0 )
  65.         pstream::releaseTypes();
  66. }
  67.  
  68. const ObjectBuilder *TStreamableTypes::Lookup( ModuleId,
  69.                                                const _TCHAR *name ) const
  70. {
  71.     unsigned loc = Types.Find(&TStreamableClass(name,0,0,0));
  72.     if( loc == UINT_MAX )
  73.         {
  74.         string msg;
  75.         msg.reserve(128);
  76.         msg = "Attempt to stream unregistered type '";
  77.         msg += name;
  78.         msg += "'";
  79.         throw xmsg(msg);
  80.         }
  81.     return Types[loc];
  82. }
  83.  
  84. void TPReadObjects::RemoveAll()
  85. {
  86.     Data.Flush();
  87. }
  88.  
  89. void TPReadObjects::RegisterObject( TStreamableBase *adr )
  90. {
  91.     Data.Add( adr );
  92. }
  93.  
  94. TStreamableBase *TPReadObjects::Find( P_id_type id )
  95. {
  96.     return Data[id];
  97. }
  98.  
  99. TPReadObjects::TPReadObjects() : Data(5,5)
  100. {
  101.     Data.Add(0);    // prime it: 0 is not a legal index.
  102. }
  103.  
  104. TPWrittenObjects::TPWrittenObjects() : CurId(0), Data(5,5)
  105. {
  106. }
  107.  
  108. void TPWrittenObjects::RemoveAll()
  109. {
  110.     CurId = 0; Data.Flush();
  111. }
  112.  
  113. void TPWrittenObjects::RegisterObject( TStreamableBase *adr )
  114. {
  115.     Data.Add( TPWObj( ((_TCHAR *)(void *)adr)+1, ++CurId ) );
  116. }
  117.  
  118. void TPWrittenObjects::RegisterVB( const TStreamableBase *adr )
  119. {
  120.     Data.Add( TPWObj( adr, ++CurId ) );
  121. }
  122.  
  123. P_id_type TPWrittenObjects::FindObject( TStreamableBase *d )
  124. {
  125.     unsigned res = Data.Find( TPWObj(((_TCHAR *)(void *)d)+1,0) );
  126.     if( res == UINT_MAX )
  127.         return 0;
  128.     else
  129.         return Data[res].Ident;
  130. }
  131.  
  132. P_id_type TPWrittenObjects::FindVB( TStreamableBase *d )
  133. {
  134.     unsigned res = Data.Find( TPWObj(d,0) );
  135.     if( res == UINT_MAX )
  136.         return 0;
  137.     else
  138.         return Data[res].Ident;
  139. }
  140.  
  141. pstream::~pstream()
  142. {
  143. }
  144.  
  145. void pstream::initTypes()
  146. {
  147.     if( types == 0 )
  148.         types = new TStreamableTypes;
  149. }
  150.  
  151. void pstream::releaseTypes()
  152. {
  153.     delete types;
  154.     types = 0;
  155. }
  156.  
  157. streampos ipstream::tellg()
  158. {
  159.     streampos res;
  160.     if( !good() )
  161.         res = streampos(EOF);
  162.     else
  163.         {
  164.         res = bp->seekoff( 0, ios::cur, ios::in );
  165.         if( res == streampos(EOF) )
  166.             clear( ios::failbit );
  167.         }
  168.     return res;
  169. }
  170.  
  171. ipstream& ipstream::seekg( streampos pos )
  172. {
  173.     if( good() )
  174.         {
  175.         objs.RemoveAll();
  176.         if( bp->seekoff( pos, ios::beg, ios::in ) == streampos(EOF) )
  177.             clear( ios::failbit );
  178.         }
  179.     return *this;
  180. }
  181.  
  182. ipstream& ipstream::seekg( streamoff off, ios::seek_dir dir )
  183. {
  184.     if( good() )
  185.         {
  186.         objs.RemoveAll();
  187.         if( bp->seekoff( off, dir, ios::in ) == streampos(EOF) )
  188.             clear( ios::failbit );
  189.         }
  190.     return *this;
  191. }
  192.  
  193. uint8 ipstream::readByte()
  194. {
  195.     int res;
  196.     if( !good() )
  197.         res = uint8(0);
  198.     else
  199.         {
  200.         res = bp->sbumpc();
  201.         if( res == EOF )
  202.             clear( ios::failbit );
  203.         }
  204.     return uint8(res);
  205. }
  206.  
  207. void ipstream::readBytes( void *data, size_t sz )
  208. {
  209.     PRECONDITION( data != 0 );
  210.     if( good() && sz > 0 )
  211.         {
  212.         if( bp->sgetn( (_TCHAR *)data, sz ) != sz )
  213.             clear( ios::failbit );
  214.         }
  215. }
  216.  
  217. void ipstream::freadBytes( void _BIDSFARDATA *data, size_t sz )
  218. {
  219.     PRECONDITION( data != 0 );
  220.  
  221.     if( good() && sz > 0 )
  222.         {
  223.         _TCHAR *buf = new _TCHAR[sz];
  224.  
  225.         if( bp->sgetn( buf, sz ) != sz )
  226.             clear( ios::failbit );
  227.         else
  228.             memcpy( data, buf, sz);
  229.  
  230.         delete [] buf;
  231.         }
  232. }
  233.  
  234. uint32 ipstream::readWord()
  235. {
  236.     if( getVersion() > 0 )
  237.         return readWord32();
  238.     else
  239.         return readWord16();
  240. }
  241.  
  242. uint16 ipstream::readWord16()
  243. {
  244.     if( !good() )
  245.         return 0;
  246.     else
  247.         {
  248.         uint16 temp;
  249.         if( bp->sgetn( (_TCHAR *)&temp, sizeof( temp ) ) != sizeof( temp ) )
  250.             clear( ios::failbit );
  251.         return temp;
  252.         }
  253. }
  254.  
  255. uint32 ipstream::readWord32()
  256. {
  257.     if( !good() )
  258.         return 0;
  259.     else
  260.         {
  261.         uint32 temp;
  262.         if( bp->sgetn( (_TCHAR *)&temp, sizeof( temp ) ) != sizeof( temp ) )
  263.             clear( ios::failbit );
  264.         return temp;
  265.         }
  266. }
  267.  
  268. uint32 ipstream::readStringLength()
  269. {
  270.     uint32 len;
  271.     if( getVersion() > 0x0100 )
  272.         {
  273.         len = readWord32();
  274.         }
  275.     else
  276.         {
  277.         len = readByte();
  278.         if( len == oldNullStringLen )
  279.             len = nullStringLen;
  280.         }
  281.     return len;
  282. }
  283.  
  284. _TCHAR *ipstream::readString()
  285. {
  286.     if( !good() )
  287.         return 0;
  288.     else
  289.         {
  290.         uint32 len = readStringLength();
  291.         if( len == nullStringLen )
  292.             return 0;
  293.  
  294.         _TCHAR *buf = new _TCHAR[size_t(len+1)];
  295.         if( buf == 0 )
  296.             return 0;
  297.         readBytes( buf, size_t(len) );
  298.         buf[size_t(len)] = EOS;
  299.         return buf;
  300.         }
  301. }
  302.  
  303. _TCHAR *ipstream::readString( _TCHAR *buf, unsigned maxLen )
  304. {
  305.     PRECONDITION( buf != 0 );
  306.  
  307.     if( !good() )
  308.         return 0;
  309.     else
  310.         {
  311.         uint32 len = readStringLength();
  312.         if( len == nullStringLen || len > maxLen-1 )
  313.             return 0;
  314.         readBytes( buf, size_t(len) );
  315.         buf[size_t(len)] = EOS;
  316.         return buf;
  317.         }
  318. }
  319.  
  320. _TCHAR _BIDSFARDATA *ipstream::freadString()
  321. {
  322.     if( !good() )
  323.         return 0;
  324.     else
  325.         {
  326.         uint32 len = readStringLength();
  327.         if( len == nullStringLen )
  328.             return 0;
  329.  
  330.         _TCHAR _BIDSFARDATA *buf = new _BIDSFARDATA _TCHAR[size_t(len)+1];
  331.         freadBytes(buf, size_t(len));
  332.         buf[size_t(len)] = EOS;
  333.         return buf;
  334.         }
  335. }
  336.  
  337. _TCHAR _BIDSFARDATA *ipstream::freadString( _TCHAR _BIDSFARDATA *buf, unsigned maxLen )
  338. {
  339.     PRECONDITION(buf != 0 );
  340.  
  341.     if( !good() )
  342.         return 0;
  343.     else
  344.         {
  345.         uint32 len = readStringLength();
  346.         if( len == nullStringLen || len > maxLen-1 )
  347.             return 0;
  348.  
  349.         freadBytes( buf, size_t(len));
  350.         buf[size_t(len)] = EOS;
  351.         return buf;
  352.         }
  353. }
  354.  
  355. void ipstream::readVersion()
  356. {
  357.     if( !good() )
  358.         version = 0;
  359.     else
  360.         {
  361.         int res = bp->sgetc();
  362.         if( res == EOF )
  363.             {
  364.             clear( ios::eofbit );
  365.             version = 0;
  366.             return;
  367.             }
  368.         if( res != versionIndicator )
  369.             version = 0;
  370.         else
  371.             {
  372.             bp->sbumpc();
  373.             version = readWord32();
  374.             }
  375.         }
  376. }
  377.  
  378. TStreamableBase _FAR *ipstream::readObject( TStreamableBase _FAR *&mem,
  379.                                             ModuleId mid )
  380. {
  381.     if( good() )
  382.         {
  383.         const ObjectBuilder *pc = readPrefix( mid );
  384.         if( pc == 0 )
  385.             mem = 0;
  386.         else
  387.             {
  388.             readData( pc, mem );
  389.             readSuffix();
  390.             }
  391.         }
  392.     return mem;
  393. }
  394.  
  395. const ObjectBuilder *ipstream::readPrefix( ModuleId mid )
  396. {
  397.     _TCHAR ch = readByte();
  398.     if( ch != '[' )
  399.         {
  400.         clear( ios::failbit );
  401.         return 0;
  402.         }
  403.  
  404.     _TCHAR name[128];
  405.     name[0] = EOS;
  406.     readString( name, sizeof name );
  407.     if( name[0] == EOS )
  408.         {
  409.         clear( ios::failbit );
  410.         return 0;
  411.         }
  412.  
  413.     TRACEX(Objstrm,0,"Reading " << name);
  414.     const ObjectBuilder *res = types->Lookup( mid, name );
  415.     WARNX(Objstrm,res==0,0,"Unrecognized class identifier: " << name);
  416.     if( res == 0 )
  417.         {
  418.         clear( ios::failbit );
  419.         return 0;
  420.         }
  421.  
  422.     return res;
  423. }
  424.  
  425. void ipstream::readData( const ObjectBuilder *c, TStreamableBase _FAR *&mem )
  426. {
  427.     TStreamer *strmr = c->Builder(mem);
  428.     mem = strmr->GetObject();
  429.  
  430.     // register the address
  431.     registerObject( mem );
  432.  
  433.     uint32 classVer = 0;
  434.     if( getVersion() > 0 )
  435.         classVer = readWord32();
  436.  
  437.     strmr->Read( *this, classVer );
  438.     delete strmr;
  439. }
  440.  
  441. void ipstream::readSuffix()
  442. {
  443.     if( !good() )
  444.         return;
  445.     _TCHAR ch = readByte();
  446.     if( ch != ']' )
  447.         clear( ios::failbit );
  448. }
  449.  
  450. TStreamableBase _FAR *ipstream::readObjectPointer( TStreamableBase _FAR *&mem,
  451.                                                    ModuleId mid )
  452. {
  453.     if( !good() )
  454.         return 0;
  455.  
  456.     _TCHAR ch = readByte();
  457.     switch( ch )
  458.         {
  459.         case pstream::ptNull:
  460.             mem = 0;
  461.             break;
  462.         case pstream::ptIndexed:
  463.             {
  464.             P_id_type index = P_id_type(readWord());
  465.             mem = find( index );
  466.             CHECK( mem != 0 );
  467.             break;
  468.             }
  469.         case pstream::ptObject:
  470.             {
  471.             const ObjectBuilder *pc = readPrefix( mid );
  472.             readData( pc, mem );
  473.             readSuffix();
  474.             break;
  475.             }
  476.         default:
  477.             clear( ios::failbit );
  478.             break;
  479.         }
  480.     return mem;
  481. }
  482.  
  483. opstream::opstream()
  484. {
  485.     objs = new TPWrittenObjects;
  486.     if( bp != 0 )
  487.         writeVersion();
  488. }
  489.  
  490. opstream::opstream( streambuf * sb )
  491. {
  492.     objs = new TPWrittenObjects;
  493.     pstream::init( sb );
  494.     writeVersion();
  495. }
  496.  
  497. streampos opstream::tellp()
  498. {
  499.     streampos res;
  500.     if( !good() )
  501.         res = streampos(EOF);
  502.     else
  503.         {
  504.         res = bp->seekoff( 0, ios::cur, ios::out );
  505.         if( res == streampos(EOF) )
  506.             clear( ios::failbit );
  507.         }
  508.     return res;
  509. }
  510.  
  511. opstream& opstream::seekp( streampos pos )
  512. {
  513.     if( good() )
  514.         {
  515.         objs->RemoveAll();
  516.         if( bp->seekoff( pos, ios::beg, ios::out ) == streampos(EOF) )
  517.             clear( ios::failbit );
  518.         }
  519.     return *this;
  520. }
  521.  
  522. opstream& opstream::seekp( streamoff pos, ios::seek_dir dir )
  523. {
  524.     if( good() )
  525.         {
  526.         objs->RemoveAll();
  527.         if( bp->seekoff( pos, dir, ios::out ) == streampos(EOF) )
  528.             clear( ios::failbit );
  529.         }
  530.     return *this;
  531. }
  532.  
  533. void opstream::writeVersion()
  534. {
  535.     if( good() )
  536.         {
  537.         writeByte( versionIndicator );
  538.         writeWord32( streamVersion );
  539.         }
  540. }
  541.  
  542. opstream& opstream::flush()
  543. {
  544.     if( bp->sync() == EOF )
  545.         clear( ios::badbit );
  546.     return *this;
  547. }
  548.  
  549. void opstream::writeByte( uint8 ch )
  550. {
  551.     if( good() )
  552.         {
  553.         if( bp->sputc( ch ) == EOF )
  554.             clear( ios::failbit );
  555.         }
  556. }
  557.  
  558. void opstream::writeBytes( const void *data, size_t sz )
  559. {
  560.     PRECONDITION( data != 0 );
  561.  
  562.     if( good() && sz > 0 )
  563.         {
  564.         if( bp->sputn( (_TCHAR *)data, sz ) != sz )
  565.             clear( ios::failbit );
  566.         }
  567. }
  568.  
  569. void opstream::writeWord16( uint16 word16 )
  570. {
  571.     if( good() )
  572.         {
  573.         if( bp->sputn( (_TCHAR *)&word16, sizeof(word16) ) != sizeof(word16) )
  574.             clear( ios::failbit );
  575.         }
  576. }
  577.  
  578. void opstream::writeWord32( uint32 word32 )
  579. {
  580.     if( good() )
  581.         {
  582.         if( bp->sputn( (_TCHAR *)&word32, sizeof(word32) ) != sizeof(word32) )
  583.             clear( ios::failbit );
  584.         }
  585. }
  586.  
  587. void opstream::fwriteBytes( const void _BIDSFARDATA *data, size_t sz )
  588. {
  589.     PRECONDITION( data != 0 );
  590.  
  591.     if( good() && sz > 0 )
  592.         {
  593.         _TCHAR *buf = new _TCHAR[sz];
  594.  
  595.         memcpy( buf, data, sz );
  596.         if( bp->sputn( (_TCHAR *)buf, sz ) != sz )
  597.             clear( ios::failbit );
  598.  
  599.         delete[] buf;
  600.         }
  601. }
  602.  
  603. void opstream::writeString( const _TCHAR *str )
  604. {
  605.     if( !good() )
  606.         return;
  607.  
  608.     if( str == 0 )
  609.         {
  610.         writeWord32( nullStringLen );
  611.         return;
  612.         }
  613.     size_t len = _tcslen( str );
  614.     writeWord32( len );
  615.     writeBytes( str, len );
  616. }
  617.  
  618. void opstream::fwriteString( const _TCHAR _BIDSFARDATA * str )
  619. {
  620.     if( !good() )
  621.         return;
  622.  
  623.     if( str == 0 )
  624.         {
  625.         writeWord32( nullStringLen );
  626.         return;
  627.         }
  628.     size_t len = _tcslen( str );
  629.     writeWord32( len );
  630.     fwriteBytes(str, len);
  631. }
  632.  
  633. #pragma warn -par
  634. void opstream::writeObject( const TStreamableBase _FAR *mem, int isPtr, ModuleId mid )
  635. {
  636.     WARNX(Objstrm,
  637.           !isPtr && findObject( CONST_CAST(TStreamableBase *,mem) ),
  638.           0,
  639.           "Pointer written before object: "     \
  640.               << _TYPENAME(mem) << '(' << (void _FAR *)mem << ')' );
  641.     if( good() )
  642.         {
  643.         writePrefix( mem );
  644.         writeData( mem, mid );
  645.         writeSuffix( mem );
  646.         }
  647. }
  648. #pragma warn +par
  649.  
  650. void opstream::writeObjectPointer( const TStreamableBase *t, ModuleId mid )
  651. {
  652.     if( good() )
  653.         {
  654.         P_id_type index;
  655.         if( t == 0 )
  656.             writeByte( pstream::ptNull );
  657.         else if( (index = findObject( CONST_CAST(TStreamableBase *,t) )) != 0 )
  658.             {
  659.             writeByte( pstream::ptIndexed );
  660.             writeWord( index );
  661.             }
  662.         else
  663.             {
  664.             writeByte( pstream::ptObject );
  665.             writeObject( t, 1, mid );
  666.             }
  667.         }
  668. }
  669.  
  670. void opstream::writePrefix( const TStreamableBase *t )
  671. {
  672.     if( good() )
  673.         {
  674.         writeByte( '[' );
  675.         writeString( _TYPENAME(t) );
  676.         }
  677. }
  678.  
  679. void opstream::writeData( const TStreamableBase *t, ModuleId mid )
  680. {
  681.     if( good() )
  682.         {
  683.         registerObject( CONST_CAST(TStreamableBase *,t) );
  684.         const ObjectBuilder *res = types->Lookup( mid, _TYPENAME(t) );
  685.         CHECKX(res,_TYPENAME(t));
  686.         TStreamer *strmr = res->Builder(CONST_CAST(TStreamableBase *,t));
  687.         writeWord32( strmr->ClassVersion() );
  688.         strmr->Write( *this );
  689.         delete strmr;
  690.         }
  691. }
  692.  
  693. void fpbase::open( const _TCHAR *b, int m, int prot )
  694. {
  695.     if( buf.is_open() )
  696.         clear(ios::failbit);        // fail - already open
  697.     else if( buf.open(b, m, prot) )
  698.         clear(ios::goodbit);        // successful open
  699.     else
  700.         clear(ios::badbit);         // open failed
  701. }
  702.  
  703. void fpbase::attach( int f )
  704. {
  705.     if( buf.is_open() )
  706.         clear(ios::failbit);
  707.     else if( buf.attach(f) )
  708.         clear(ios::goodbit);
  709.     else
  710.         clear(ios::badbit);
  711. }
  712.  
  713. void fpbase::close()
  714. {
  715.     if( buf.close() )
  716.         clear(ios::goodbit);
  717.     else
  718.         clear(ios::failbit);
  719. }
  720.  
  721. void fpbase::setbuf(_TCHAR* b, int len)
  722. {
  723.     if( buf.setbuf(b, len) )
  724.         clear(ios::goodbit);
  725.     else
  726.         clear(ios::failbit);
  727. }
  728.  
  729. //
  730. //  These operators are not friends of string, so
  731. //  they must use only the public interface.
  732. //
  733. #if defined(BI_NAMESPACE)
  734. namespace ClassLib {
  735. #endif
  736.  
  737. opstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator << ( opstream _BIDSFAR& os,
  738.                                                       const string _BIDSFAR& str )
  739. {
  740.     os.writeString( str.c_str() );
  741.     return os;
  742. }
  743.  
  744. ipstream _BIDSFAR& _BIDSENTRY _BIDSFUNC operator >> ( ipstream _BIDSFAR& is,
  745.                                                       string _BIDSFAR& str )
  746. {
  747.     if( is.good() )
  748.         {
  749.         uint32 len = is.readStringLength();
  750.         if( len == nullStringLen )
  751.             str = "";
  752.         else
  753.             {
  754.             _TCHAR *temp = new _TCHAR[size_t(len)+1];
  755.             is.readBytes( temp, size_t(len) );
  756.             temp[size_t(len)] = EOS;
  757.             str = temp;
  758.             delete [] temp;
  759.             }
  760.         }
  761.     return is;
  762. }
  763.  
  764. #if defined(BI_NAMESPACE)
  765. }     // namespace ClassLib
  766. #endif
  767.